import i18n from "../../i18n";

import { SerialPort } from 'serialport'
import { InterByteTimeoutParser } from '@serialport/parser-inter-byte-timeout'

import { receiveJson, settingRegisterSizeJSON, settingArray, nameRegisterJSON } from "@/utils/util";


import { Message } from 'element-ui'
const state = {
    deviceNameList:[],
    deviceName: "",
    serialPort: null,

    lali: null,
    step: 0,
    firstTimeValue: 0,
    secondTimeValue: 0,
    thirdTimeValue:0,

    testMeasure: null,
    mockInterval: null,
};

const mutations = {
    CLOSE: (state) => {
        if (state.serialPort != null && state.serialPort.notOpen) {
            state.serialPort.close(
                function (err) {
                    if (err) {
                        console.log('Error close port: ', err.message);
                        Message.error(
                            {
                                showClose: true,
                                message: i18n.t("serialPort.closeError")
                            }
                        );
                    } else {
                        state.serialPort = null;
                    }
                }
            );
        }
    },
    RE_INIT_PORT: (state, parameter) => {
        let {deviceName, baudRate } = parameter;
        state.baudRate = 9600;
        baudRate = 9600;
        if (state.serialPort != null && state.serialPort.isOpen) {
           if (state.deviceName === deviceName) {
               return;
           } else {
               state.serialPort.close();
           }
        }
        state.deviceName = deviceName;
        state.serialPort = new SerialPort({ path: deviceName, baudRate: baudRate, autoOpen:false});
        const parse = state.serialPort.pipe(new InterByteTimeoutParser({interval: 100})); // 100ms

        state.serialPort.open(function(err){
            if(err){
                console.log('Error opening port: ',err.message);
                state.serialPort = null;
                Message.error(
                    {
                        showClose: true,
                        message: i18n.t("serialPort.openError") + deviceName
                    }
                );
            } else {
                parse.on("data", (data) => {
                    console.log(data)
                    let decodeDataArray = extractData(data);

                    if (decodeDataArray === undefined || decodeDataArray === null || decodeDataArray.length === 0) {
                        return;
                    }
                    console.info("receiveData " + JSON.stringify(decodeDataArray))
                    for (let index = 0; index < decodeDataArray.length; index++) {
                        let item = decodeDataArray[index];

                        // TODO 需要根据不同的数字来做调整
                        let val = parseIntCustom(item.value, 4);
                        if (nameRegisterJSON["lali"] === item.op) {
                            state.lali = new Date().getTime() + "$" + Math.round(val);
                        }

                        if (nameRegisterJSON["first"] === item.op) {
                            console.info("first value " + val);
                            state.firstTimeValue = new Date().getTime() + "$" + Math.round(val);
                        }
                        if (nameRegisterJSON["second"] === item.op) {
                            console.info("second value " + val);
                            state.secondTimeValue = new Date().getTime() + "$" + Math.round(val);
                        }
                        if (nameRegisterJSON["third"] === item.op) {
                            console.info("third value " + val);
                            state.thirdTimeValue = new Date().getTime() + "$" + Math.round(val);
                        }
                        if (nameRegisterJSON["step"] === item.op) {
                            console.info("current step is " + val);
                            state.step = new Date().getTime() + "$" + val;
                        }
                    }
                });
            }
        });
    },
    NULL_SEND_DATA:(state) => {
      state.sendDataStatus = null
    },
    SEND_DATA:(state, parameter) => {
        let {value, type, action} = parameter;
        state.action = action;
        if (state.serialPort == null) {
            Message.error(
                {
                    showClose: true,
                    message: i18n.t("serialPort.notOpen"),
                }
            );
            state.sendDataStatus = false;
        }
        if (type === 1) {
            state.serialPort.write(value, (error) => {
                if (error) {
                    showMessage(action, false);
                } else {
                    showMessage(action, true);
                    if (action==="start") {
                        startInit();
                    } else if (action === "stop") {
                        stop();
                    }
                    state.sendDataStatus = true
                }
            });
        } else if (type === 2) {
            state.serialPort.write(Buffer.from(value), (error) => {
                if (error) {
                    showMessage(action, false);
                } else {
                    showMessage(action, true);
                    if (action==="start") {
                        startInit();
                    } else if (action === "stop") {
                        stop();
                    }
                    state.sendDataStatus = true
                }
            });
        } else if (type === 3) {
            state.serialPort.write(new Uint8Array(value), (error) => {
                if (error) {
                    showMessage(action, false);
                } else {
                    showMessage(action, true);
                    if (action==="start") {
                        startInit();
                    } else if (action === "stop") {
                        stop();
                    }
                    state.sendDataStatus = true
                    // console.info("send data success")
                }
            });
        }
    },
    INIT_DEVICE_NAMES(state) {
        SerialPort.list().then(ports=>{
            state.deviceNameList = [];
            ports.forEach(port => {
                console.log(port);
                state.deviceNameList.push({
                    friendlyName: port.friendlyName,
                    path: port.path
                });
            })
        })
    },
    SET_TEST_ELECTRIC(state, testElectric) {
        state.testElectric = testElectric
    },
    SET_TEST_MEASURE(state, testMeasure) {
        state.measureTemp = testMeasure;
    },
    SET_TEST_COLD_MEASURE(state, testMeasure) {
        state.coldTemp = testMeasure
    },
    SET_TEST_SPEED(state, speed) {
        state.speed = speed
    }
};

function showMessage(action, success) {
    if (success) {
        if (action === 'btnNeedResponse'){
                Message.success(
                    {
                        showClose: true,
                        message: i18n.t("serialPort.btnResponseSuccess"),
                    }
                );
        }
        return;
    } else {
        if (action === "start") {
            Message.error(
                {
                    showClose: true,
                    message: i18n.t("serialPort.startError"),
                }
            );
        } else if (action === "stop") {
            Message.error(
                {
                    showClose: true,
                    message: i18n.t("serialPort.stopError"),
                }
            );
        } else if (action === 'findAction'){
            Message.error(
                {
                    showClose: true,
                    message: i18n.t("serialPort.findActionError"),
                }
            );
        }  else {
            Message.error(
                {
                    showClose: true,
                    message: i18n.t("serialPort.writeError"),
                }
            );
        }
    }
}

function startInit() {

}

function stop() {

}

const actions = {
    SEND_DATA({ commit }, playLoad) {
        return new Promise((resolve) => {
            commit("NULL_SEND_DATA")
            commit('SEND_DATA', playLoad);
            resolve()
        })
    },
    RE_INIT_PORT({commit}, playLoad) {
        return new Promise((resolve) => {
            commit('RE_INIT_PORT', playLoad);
            resolve()
        })
    },
    SET_TEST_ELECTRIC({commit}, testElectric) {
        commit('SET_TEST_ELECTRIC', testElectric);
    },
    SET_TEST_MEASURE({commit}, testMeasure) {
        commit('SET_TEST_MEASURE', testMeasure);
    }
};

function extractData(byteArray) {
    // 分片数据的处理
    let values = bytes2HexString(byteArray).toUpperCase();
    let sendHead = values.substr(0, 4);
    if(sendHead !== "5AA5"){
        return [];
    }

    let result = [];

    let splitArray = splitData(values);
    if (isEmptyObject(splitArray) || splitArray.length === 0) {
        return result;
    }

    for (let i = 0; i < splitArray.length; i++) {

        let valueStr = splitArray[i];
        let op = valueStr.substr(8, 4);
        // 所有数据的接受
        let length = parseInt(valueStr.substr(4,2), 16);
        let totalValueLength = length * 2;
        // length check
        if (valueStr.length !== totalValueLength + 6) {
            continue;
        }


        let dataType = valueStr.substr(6, 2);
        let dataStart = 12;
        if(dataType === "83"){
            dataStart = 14;
        }

        if(op === "6300") { //仪器状态接受数据处理
            result.push(
                {
                    "op" : op.toUpperCase(),
                    "valueLength" : 4,
                    "value" : valueStr.substr(dataStart)
                 }
            );
        } else {  // 其他数据的处理
            let firstLength = receiveJson[op];
            if (isEmptyObject(firstLength)) {
                // 设置参数的解析
                let settingSize = settingRegisterSizeJSON[op.toUpperCase()];
                if (isEmptyObject(settingSize)) {
                    continue;
                }

                let index = 0;
                for (; index < settingArray.length; index++) {
                    if (settingArray[index] === op.toUpperCase()) {
                        break;
                    }
                }

                // 按照settingArray顺序解析
                let start = 0;
                let curValueLength = valueStr.length - dataStart;
                while (start < curValueLength && index < settingArray.length) {
                    let size = settingRegisterSizeJSON[op];
                    if(isEmptyObject(size)){
                        size = 4;
                    }
                    if(start + size <= curValueLength){
                        result.push(
                            {
                                "op" : settingArray[index].toUpperCase(),
                                "valueLength" : size,
                                "value" : valueStr.substr(dataStart + start, size)
                            }
                        )
                    } else {
                        result.push(
                            {
                                "op" : settingArray[index].toUpperCase(),
                                "valueLength" : size,
                                "value" : valueStr.substr(dataStart + start)
                            }
                        )
                    }
                    index++;
                    start = start + size;
                }
            } else {
                // 多数据的支持
                if (firstLength >= totalValueLength){  //单个数据的返货和接口
                    result.push({
                        "op" : op,
                        "valueLength" : firstLength,
                        "value" : valueStr.substr(dataStart)
                    });
                } else {  // 批量数据的发送和接口，必须连续
                    let start = 0;
                    let opInt = parseInt(op, 16);
                    let index = 0;
                    let curValueLength = valueStr.length - dataStart;
                    while (start < curValueLength) {
                        let curOp = (opInt + index).toString(16).toUpperCase();
                        let size = receiveJson[curOp];
                        if(isEmptyObject(size)){
                            size = 4;
                        }
                        if(start + size <= curValueLength){
                            result.push(
                                {
                                    "op" :(opInt + index).toString(16).toUpperCase(),
                                    "valueLength" : size,
                                    "value" : valueStr.substr(dataStart + start, size)
                                }
                            )
                        } else {
                            result.push(
                                {
                                    "op" : (opInt + index).toString(16).toUpperCase(),
                                    "valueLength" : size,
                                    "value" : valueStr.substr(dataStart + start)
                                }
                            )
                        }
                        index++;
                        start = start + size;
                    }
                    // console.info("result is " + JSON.stringify(result))
                }
            }
        }
    }

    return result;

}

function splitData(valueList) {

    let arr = valueList.split("5AA5");
    let ans = [];
    for(let i = 1; i < arr.length; i++) {
        ans.push("5AA5" + arr[i]);
    }
    return ans;

}

function bytes2HexString (arrBytes) {
    let str = "";
    for (let i = 0; i < arrBytes.length; i++) {
        let tmp;
        let num = arrBytes[i];
        if (num < 0) {
            tmp = (255+num+1).toString(16);
        } else {
            tmp = num.toString(16);
        }
        if (tmp.length === 1) {
            tmp = "0" + tmp;
        }
        str += tmp;
    }
    return str;
}

function isEmptyObject(value) {
    return value === undefined || value === null;
}

function parseIntCustom(value, size) {
    if (size === 8) {
        return parseInt(value, 16);
    }

    // size 为 4的情况讨论
    let intValue = parseInt(value, 16);
    if (intValue > 32767) {
        return intValue - 65536;
    } else {
        return intValue;
    }

}


export default {
    namespaced: true,
    state,
    mutations,
    actions
}

